package com.iflytek.iot.platform.tracing;

import cn.zull.tracing.core.TraceThreadLocal;
import cn.zull.tracing.core.after.TracingLogHandler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.iflytek.iot.common.utils.DateUtils;
import com.iflytek.iot.common.utils.JsonUtils;
import com.iflytek.iot.platform.IotTraceLogEntity;
import com.iflytek.iot.platform.tracing.constant.Constants;
import com.iflytek.iot.platform.tracing.threadlocal.IotTracingThreadLocal;
import com.iflytek.iot.platform.tracing.threadlocal.ThreadLocalEntity;
import com.iflytek.iot.platform.util.LogBackUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.skywalking.apm.dependencies.com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;

/**
 * @author zurun
 * @date 2019/2/13 11:31:06
 */
@Slf4j
@Component
public class IotTracingLogHandler implements TracingLogHandler<IotTraceLogEntity> {
    @Value("${tracing.user-defined.type}")
    private String traceType;
    @Value("${tracing.user-defined.room}")
    private String traceRoom;
    @Value("${tracing.retcode:code,error_code,result,error,resultCode}")
    private String retCodes;
    @Value("${tracing.retdesc:desc,error_msg,message,error_description,description,resultInfo}")
    private String retDescs;
    @Autowired
    LogBackUtil logBackUtil;
    private Set<String> consumer= Sets.newHashSet("dubbo-consumer","RestTemplate","rocketmq-provider");

    /**
     * 配置是否发送日志
     */
    @Value("${log.isSend:true}")
    private boolean isSendLog;

    @Override
    public void handler(IotTraceLogEntity traceLog) {
        if(isSendLog) {
            try {
                if("dubbo-provider".equals(traceLog.getTraceType())){
                    return;
                }
                ThreadLocalEntity entity = IotTracingThreadLocal.getEntity();
                // 统一日期格式
                traceLog.setCtm(DateUtils.long2Str(Long.parseLong(traceLog.getCtm()),DateUtils.YYYY_MM_DD_HH_MM_SS_SSS));
                traceLog.setEtm(IotTracingLogHandler.stampToDate(IotTracingLogHandler.dateToStamp(traceLog.getEtm())));
                traceLog.setStm(IotTracingLogHandler.stampToDate(IotTracingLogHandler.dateToStamp(traceLog.getStm())));
                traceLog.setRoom(traceRoom);
                traceLog.setType(traceType);
                traceLog.setCmd(entity.getCmd());
                traceLog.setPodid(entity.getPodid());
                traceLog.setInner(entity.getInner());
                traceLog.setUtm(traceLog.getCost());
                traceLog.setLocalip(traceLog.getEndPoint());
                traceLog.setSequenceNo(entity.getSequenceNo());
                if(StringUtils.isBlank(traceLog.getLocalip())) {
                    traceLog.setLocalip(Constants.LOCALHOST);
                }
                if(StringUtils.isBlank(traceLog.getRoom())) {
                    traceLog.setRoom(Constants.ROOM);
                }
                if(StringUtils.isNotBlank(entity.getCpname())) {
                    traceLog.setCpname(entity.getCpname());
                }
                if(StringUtils.isNotBlank(entity.getDeviceid())) {
                    traceLog.setDeviceid(entity.getDeviceid());
                }
                if(StringUtils.isNotBlank(entity.getCtei())) {
                    traceLog.setCtei(entity.getCtei());
                }
                if(StringUtils.isNotBlank(entity.getCaller())) {
                    traceLog.setCaller(entity.getCaller());
                }
                if(StringUtils.isNotBlank(entity.getUid())) {
                    traceLog.setUid(entity.getUid());
                }
                if(StringUtils.isNotBlank(entity.getRetcode())) {
                    traceLog.setRetcode(entity.getRetcode());
                }
                if(StringUtils.isNotBlank(entity.getRetdesc())) {
                    traceLog.setRetdesc(entity.getRetdesc());
                }
                if(StringUtils.isNotBlank(entity.getOsid())){
                    traceLog.setOsid(entity.getOsid());
                }
                if(StringUtils.isNotBlank(entity.getManufacturer())) {
                    traceLog.setManufacturer(entity.getManufacturer());
                }
                if(StringUtils.isNotBlank(entity.getModel())) {
                    traceLog.setModel(entity.getModel());
                }
                if (StringUtils.isNotBlank(entity.getBrandname())) {
                    traceLog.setBrandname(entity.getBrandname());
                }
                if (StringUtils.isNotBlank(entity.getDevicesn())) {
                    traceLog.setDevicesn(entity.getDevicesn());
                }
                if (StringUtils.isNotBlank(entity.getPlatform())) {
                    traceLog.setPlatform(entity.getPlatform());
                }
                if(StringUtils.isNotBlank(entity.getCategory())) {
                    traceLog.setCategory(entity.getCategory());
                }
                // 2019/6/24 修复xpush响应包和请求包日志记录缺失bug
                if(StringUtils.isNotBlank(entity.getReqpkg())){
                    traceLog.setReqpkg(entity.getReqpkg());
                }

                // 修复Rest请求调用第三方时，响应体响应码和错误信息记录不正确问题 20190826
                if (traceLog.getRespkg() != null) {
                    boolean flag = JsonUtils.isJSONValid(traceLog.getRespkg());
                    if (flag) {
                        JSONObject jsonObject;
                        try {
                            jsonObject = JSON.parseObject(traceLog.getRespkg());
                        } catch (Exception e) {
                            log.info("[全链路日志]：日志响应报文JSON解析失败，响应报文respkg = {}", traceLog.getRespkg());
                            jsonObject = null;
                        }
                        if (jsonObject != null) {
                            String retCode = null;
                            String retDesc = null;
                            String[] retCodeStr = retCodes.split(",");
                            String[] retDescStr = retDescs.split(",");
                            String onlineFlag = jsonObject.getString("OnlineFlag");
                            if ("N".equals(onlineFlag)) {
                                traceLog.setRetcode("100009");
                                traceLog.setRetdesc("设备不在线");
                            } else {
                                for (String s : retCodeStr) {
                                    if (StringUtils.isNotBlank(jsonObject.getString(s))) {
                                        retCode = String.valueOf(jsonObject.getString(s));
                                        traceLog.setRetcode(retCode);
                                        break;
                                    }
                                }
                                for (String ss : retDescStr) {
                                    if (StringUtils.isNotBlank(jsonObject.getString(ss))) {
                                        retDesc = jsonObject.getString(ss);
                                        traceLog.setRetdesc(retDesc);
                                        break;
                                    }
                                }
                            }
                        }
                    }else {
                        log.debug("异常json={}", traceLog.getRespkg());
                    }
                }
                traceLog.setTraceId(TraceThreadLocal.getTraceId());

                logBackUtil.sendLog(traceLog);
            } catch (Exception e) {
                log.error("[全链路日志] 捕获到的异常信息为:{}", e.getMessage());
                log.error("[IotTracingLogHandler]: e={}", e);
            } finally {
                final String traceType=traceLog.getTraceType();
                if(!consumer.contains(traceType)){
                    IotTracingThreadLocal.remove();
                }
            }
        }
    }

    public static void main(String[] args) throws ParseException{
        System.out.println(dateToStamp("2019-04-26 09:20:58:443"));
        System.out.println(stampToDate(dateToStamp("2019-04-26 09:20:58:443")));
    }

    public static String dateToStamp(String s) throws ParseException {
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
        Date date = simpleDateFormat.parse(s);
        long ts = date.getTime();
        res = String.valueOf(ts);
        return res;
    }

    public static String stampToDate(String s){
        String res;
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DateUtils.YYYY_MM_DD_HH_MM_SS_SSS);
        long lt = new Long(s);
        Date date = new Date(lt);
        res = simpleDateFormat.format(date);
        return res;
    }
}